package com.example.documentconvertor.util;

import com.example.documentconvertor.controller.IndexController;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.graphics.PdfMargins;
import org.springframework.boot.system.ApplicationHome;

import java.awt.geom.Point2D;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static org.springframework.util.FileCopyUtils.BUFFER_SIZE;

public class Utils {

    public static ActiveXComponent word = null;
    public static Dispatch document = null;
    public static Dispatch wordDoc = null;

    /**
     * 获取jar包所在目录路径
     * @return 路径
     */
    public static String getRootPath(){
        ApplicationHome ah = new ApplicationHome(IndexController.class);
        String docStorePath = ah.getSource().getParentFile().toString();
        return docStorePath;
    }

    /**
     * 取得某一路径下所有的pdf
     * @param path 路径
     * @return
     */
    public static File[] getSplitFiles(String path) {
        File f = new File(path);
        File[] fs = f.listFiles();
        return fs;
    }

    /**
     * 合并word
     * @param docPath 待合并的word的路径
     * @param savepaths 合并以后输出路径
     * @return
     */
    public static boolean mergeWordDocument(String docPath,String savepaths){
        File[] fs = getSplitFiles(docPath);
        List<String> fileList = new ArrayList<>();
        for (File f:fs) {
            fileList.add(String.valueOf(f));
        }
        if (fileList.size() == 0 || fileList == null) {
            return false;
        }
        //对文件排序,取出数字进行排序
        fileList.sort(new Comparator<String>() {
            @Override
            public int compare(String u1, String u2) {
                String temp1 = u1.substring(u1.lastIndexOf("$division") + 9);
                String temp2 = u2.substring(u2.lastIndexOf("$division") + 9);
                String compareNum1 = temp1.substring(0, temp1.lastIndexOf("."));
                String compareNum2 = temp2.substring(0, temp2.lastIndexOf("."));
                int diff = Integer.parseInt(compareNum1) - Integer.parseInt(compareNum2);
                if (diff > 0) {
                    return 1;
                } else if (diff < 0) {
                    return -1;
                }
                return 0; //相等为0
            }
        });
        // 判断文件是否存在
        if( new File(savepaths).exists() ){
            try {
                new File(savepaths).delete();
                new File(savepaths).createNewFile();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            //打开word
            ActiveXComponent app = new ActiveXComponent("Word.Application");//启动word
            // 设置word不可见
            app.setProperty("Visible", new Variant(false));
            //获得documents对象
            Dispatch docs = app.getProperty("Documents").toDispatch();
            //打开第一个文件
            Dispatch doc = Dispatch.invoke(docs, "Open", Dispatch.Method,
                    new Object[] { (String) fileList.get(0), new Variant(false), new Variant(true) },
                    new int[3]).toDispatch();

            //追加文件
            for (int i = 1; i < fileList.size(); i++) {
                Dispatch selection = Dispatch.get(app, "Selection").toDispatch();
                // 到文档末尾
                Dispatch.call(selection, "EndKey" , "6" );
                //插入分页符
                Dispatch.call(app.getProperty("Selection").toDispatch(),"InsertBreak", new Variant(7));

                Dispatch.invoke(app.getProperty("Selection").toDispatch(),
                        "insertFile", Dispatch.Method, new Object[] {
                                (String) fileList.get(i), "",
                                new Variant(false), new Variant(false),
                                new Variant(false) }, new int[3]);
            }
            //保存新的word文件
            Dispatch.invoke(doc, "SaveAs", Dispatch.Method,
                    new Object[] { savepaths, new Variant(1) }, new int[3]);
            Variant f = new Variant(false);
            Dispatch.call(doc, "Close", f);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除目录
     * @param workspaceRootPath
     */
    public static void clearFiles(String workspaceRootPath){
        File file = new File(workspaceRootPath);
        if(file.exists()){
            deleteFile(file);
        }
    }

    /**
     * 删除文件
     * @param file
     */
    public static void deleteFile(File file){
        if(file.isDirectory()){
            File[] files = file.listFiles();
            for(int i=0; i<files.length; i++){
                deleteFile(files[i]);
            }
        }
        file.delete();
    }

    /**
     * WORD组件初始化
     */
    public static void wordInit() {
        ComThread.InitMTA(true);
        word = new ActiveXComponent("Word.Application");
        Dispatch.put(word, "Visible", new Variant(false));
        word.setProperty("AutomationSecurity", new Variant(3)); // 禁用宏
        document = word.getProperty("Documents").toDispatch();
    }

    /**
     * 关闭所有资源
     */
    public static void release() {
        // 始终释放资源
        if(word != null){
            word.invoke("Quit", new Variant[] {});
        }
        ComThread.Release();
    }

    /**

     * 压缩成ZIP 方法2
     * @param srcFiles 需要压缩的文件列表
     * @param out     压缩文件输出流
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    public static void toZip(List<File> srcFiles , OutputStream out)throws RuntimeException {
        ZipOutputStream zos = null ;
        try {
            zos = new ZipOutputStream(out);
            for (File srcFile : srcFiles) {
                byte[] buf = new byte[BUFFER_SIZE];
                zos.putNextEntry(new ZipEntry(srcFile.getName()));
                int len;
                FileInputStream in = new FileInputStream(srcFile);
                while ((len = in.read(buf)) != -1){
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                in.close();
            }
            long end = System.currentTimeMillis();
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils",e);
        }finally{
            if(zos != null){
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 每10页分一次pdf
     * @param count 总页数
     * @param pdfDocument pdf
     * @param destPath 目标路径
     */
    public static void spitPdf(int count, PdfDocument pdfDocument, String destPath) {
        int offset = 10;
        int copies = count/offset;
        for (int i = 0; i<copies; i++){
            PdfDocument splitpdf = new PdfDocument();
            PdfPageBase page;
            for(int j = offset*i;j<offset*(i+1);j++)
            {
                page = splitpdf.getPages().add(pdfDocument.getPages().get(j).getSize(), new PdfMargins(0));
                pdfDocument.getPages().get(j).createTemplate().draw(page, new Point2D.Float(0,0));
            }
            splitpdf.saveToFile(destPath+"$division"+i+".pdf");
        }
        //对余数处理
        if(count-copies*offset>0){
            PdfDocument splitpdf = new PdfDocument();
            PdfPageBase page;
            for(int j = copies*offset;j<count;j++)
            {
                page = splitpdf.getPages().add(pdfDocument.getPages().get(j).getSize(), new PdfMargins(0));
                pdfDocument.getPages().get(j).createTemplate().draw(page, new Point2D.Float(0,0));
            }
            splitpdf.saveToFile(destPath+"$division"+copies+".pdf");
        }
    }
}
